// Cliente que lee y muestra la informaci�n que le env�a un Servidor.
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;


public class Cliente extends JFrame {

    private JTextField campoIntroducir;
    private JTextArea areaPantalla;
    private ObjectOutputStream salida;
    private ObjectInputStream entrada;
    private String mensaje = "";
    private String servidorChat;
    private Socket cliente;
    //Tray ICON
    
    private SystemTray tray;
    private final TrayIcon trayIcon;

    // inicializar servidorChat y configurar GUI
    public Cliente(String host) {
        super("COMUNICACION INTERNA");
        Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/comix.png"));
        trayIcon = new TrayIcon(image, "Software Comunicacion", null);
        trayIcon.setToolTip("Departamento de Sistema - Ronaldo Tinoco - Software Comunicacion");
        servidorChat = host; // establecer el servidor al que se va a conectar este cliente

        Container contenedor = getContentPane();

        // crear campoIntroducir y registrar componente de escucha
        campoIntroducir = new JTextField();
        campoIntroducir.setEditable(false);
        campoIntroducir.addActionListener(
                new ActionListener() {

                    // enviar mensaje al servidor
                    public void actionPerformed(ActionEvent evento) {
                        enviarDatos(evento.getActionCommand());
                        campoIntroducir.setText("");
                    }
                });

        contenedor.add(campoIntroducir, BorderLayout.NORTH);

        // crear areaPantalla
        areaPantalla = new JTextArea();
        contenedor.add(new JScrollPane(areaPantalla),
                BorderLayout.CENTER);

        setSize(300, 150);
        setVisible(true);
        
        
        if (SystemTray.isSupported()) {
            tray = SystemTray.getSystemTray();
            MouseListener mouseListener = new MouseListener() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    //System.exit(0);
                }

                @Override
                public void mousePressed(MouseEvent e) {
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                }

                @Override
                public void mouseExited(MouseEvent e) {
                }
            };
            trayIcon.setImageAutoSize(true);
            trayIcon.addMouseListener(mouseListener);
            try {
                tray.add(trayIcon);
                //trayIcon.displayMessage("Welcome", "Bienvenido", TrayIcon.MessageType.INFO);
            } catch (AWTException e) {
                System.err.println("No se pudo agregar el ícono a la barra tray");
            }
        } else {
            //  System Tray is not supported
        }
    } // fin del constructor de Cliente

    // conectarse al servidor y procesar mensajes del servidor
    private void ejecutarCliente() {
        // conectarse al servidor, obtener flujos, procesar la conexi�n
        try {
            conectarAServidor(); // Paso 1: crear un socket para realizar la conexi�n
            obtenerFlujos();      // Paso 2: obtener los flujos de entrada y salida
            procesarConexion(); // Paso 3: procesar la conexi�n
        } // el servidor cerr� la conexi�n
        catch (EOFException excepcionEOF) {
            establecerCampoTextoEditable(false);
            mostrarMensaje("\nEl cliente termino la conexion\n\n");
            mostrarMensaje("Intentando realizar conexion...\n");
//            try {
//                //areaPantalla.setText("");
//                Thread.sleep(500);
//            } catch (InterruptedException ex) {
//                //Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
//            }
            ejecutarCliente();
        } // procesar los problemas que pueden ocurrir al comunicarse con el servidor
        catch (IOException excepcionES) {
            //areaPantalla.setText("");
            try {
                //areaPantalla.setText("");
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                //Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
            }
            ejecutarCliente();
            //excepcionES.printStackTrace();
        } finally {
            cerrarConexion(); // Paso 4: cerrar la conexi�n
        }

    } // fin del m�todo ejecutarCliente

    // conectarse al servidor
    private void conectarAServidor() throws IOException {
        mostrarMensaje(".");
        // crear Socket para realizar la conexi�n con el servidor
        cliente = new Socket(InetAddress.getByName(servidorChat), 12345);

        // mostrar la informaci�n de la conexi�n
        mostrarMensaje("Conectado a: "
                + cliente.getInetAddress().getHostName() + "\n");
    }

    // obtener flujos para enviar y recibir datos
    private void obtenerFlujos() throws IOException {
        // establecer flujo de salida para los objetos
        salida = new ObjectOutputStream(cliente.getOutputStream());
        salida.flush(); // vac�ar b�fer de salida para enviar informaci�n de encabezado

        // establecer flujo de entrada para los objetos
        entrada = new ObjectInputStream(cliente.getInputStream());

        mostrarMensaje("\nSe recibieron los flujos de E/S\n");
    }

    // procesar la conexi�n con el servidor
    private void procesarConexion() throws IOException {
        // habilitar campoIntroducir para que el usuario del cliente pueda enviar mensajes
        establecerCampoTextoEditable(true);

        do { // procesar mensajes enviados del servidor

            // leer mensaje y mostrarlo en pantalla
            try {
                mensaje = (String) entrada.readObject();
                trayIcon.displayMessage("PORT-0", "COM-PUERTO-CERO", TrayIcon.MessageType.INFO);
                mostrarMensaje("\n" + mensaje);
                campoIntroducir.requestFocus();
            } // atrapar los problemas que pueden ocurrir al leer del servidor
            catch (ClassNotFoundException excepcionClaseNoEncontrada) {
                mostrarMensaje("\nSe recibio un objeto de tipo desconocido");
            }

        } while (!mensaje.equals("SERVIDOR>>> TERMINAR"));

    } // fin del m�todo procesarConexion

    // cerrar flujos y socket
    private void cerrarConexion() {
        //mostrarMensaje( "\nCerrando conexi�n" );
        establecerCampoTextoEditable(false); // deshabilitar campoIntroducir

        try {
            salida.close();
            entrada.close();
            cliente.close();
        } catch (IOException excepcionES) {
            //excepcionES.printStackTrace();
        }
    }

    // enviar mensaje al servidor
    private void enviarDatos(String mensaje) {
        // enviar objeto al servidor
        try {
            salida.writeObject("MMRP>>> " + mensaje);
            salida.flush();
            mostrarMensaje("\nMMRP>>> " + mensaje);
        } // procesar los problemas que pueden ocurrir al enviar el objeto
        catch (IOException excepcionES) {
            areaPantalla.append("\nError al escribir el objeto");
        }
    }

    // m�todo utilitario que es llamado desde otros subprocesos para manipular a 
    // areaPantalla en el subproceso despachador de eventos
    private void mostrarMensaje(final String mensajeAMostrar) {
        // mostrar mensaje del subproceso de ejecuci�n de la GUI
        SwingUtilities.invokeLater(
                new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente

                    public void run() // actualiza areaPantalla
                    {
                        areaPantalla.append(mensajeAMostrar);
                        areaPantalla.setCaretPosition(
                                areaPantalla.getText().length());
                    }
                } // fin de la clase interna
                ); // fin de la llamada a SwingUtilities.invokeLater
    }

    // m�todo utilitario que es llamado desde otros subprocesos para manipular a 
    // campoIntroducir en el subproceso despachador de eventos
    private void establecerCampoTextoEditable(final boolean editable) {
        // mostrar mensaje del subproceso de ejecuci�n de la GUI
        SwingUtilities.invokeLater(
                new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente

                    public void run() // establece la capacidad de modificar campoIntroducir
                    {
                        campoIntroducir.setEditable(editable);
                    }
                } // fin de la clase interna
                ); // fin de la llamada a SwingUtilities.invokeLater
    }

    public static void main(String args[]) {


        Cliente aplicacion;

        if (args.length == 0) {
            //192.168.5.96
            //aplicacion = new Cliente("192.168.5.96");
            aplicacion = new Cliente("5.5.1.2");
        } else {
            aplicacion = new Cliente(args[ 0]);
        }
        aplicacion.mostrarMensaje("Intentando realizar conexion A:"+aplicacion.servidorChat+"...\n");
        aplicacion.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        aplicacion.ejecutarCliente();
    }
} // fin de la clase Cliente